package com.sky.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.RedisConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Category;
import com.sky.entity.Dish;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.CategoryMapper;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.result.Result;
import com.sky.service.CategoryService;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class DishServiceImpl implements DishService {

    @Autowired
    private DishMapper dishMapper;

    @Autowired
    private DishFlavorMapper dishFlavorMapper;

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private SetmealDishMapper setmealDishMapper;

    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 添加菜品
     * @param dishDTO
     * @return
     */
    @Transactional
    @Override
    public Result insertDish(DishDTO dishDTO) {
        //创建实体类并属性拷贝
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO,dish, "flavors");
        dish.setStatus(StatusConstant.DISABLE);
        //插入数据库
        dishMapper.insert(dish);
        if (dishDTO.getFlavors() == null || dishDTO.getFlavors().isEmpty()) {
            //返回成功
            return Result.success();
        }
        dishFlavorMapper.insertBatch(dishDTO.getFlavors(), dish.getId());
        //返回成功
        return Result.success();
    }

    /**
     * 菜品分页查询
     * @param dishPageQueryDTO
     * @return
     */
    @Override
    public Result<Map<String, Object>> queryByPage(DishPageQueryDTO dishPageQueryDTO) {
        //创建Map对象接收数据
        HashMap<String, Object> result = new HashMap<>();
        //查询菜品信息
        PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());
        List<DishVO> dishList = dishMapper.queryByPage(dishPageQueryDTO);
        //设置返回结果
        result.put("total",dishList.size());
        result.put("records",dishList);
        return Result.success(result);
    }


    /**
     * 菜品删除
     * @param ids
     * @return
     */
    @Override
    @Transactional
    public Result deleteByIds(Integer[] ids) {
        //判断菜品是否启售
        for (Integer id : ids) {
            Dish dish = dishMapper.queryById(id);
            if(dish.getStatus() == StatusConstant.ENABLE) throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
        }
        //判断菜品是否关联套餐
        Long count = setmealDishMapper.queryByDishIds(ids);
        if(count > 0) throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        for (Integer id : ids) {
            //删除菜品关联的口味
            dishFlavorMapper.deleteByDishId(id);
        }

        //删除菜品
        dishMapper.deleteById(ids);

        return Result.success();
    }


    /**
     * 菜品主键查询
     * @param id
     * @return
     */
    @Override
    public Result<DishVO> queryById(Integer id) {
        //查询菜品信息
        DishVO dishVo = dishMapper.queryByDishVo(id);
        //查询菜品关联的口味
        dishVo.setFlavors(dishFlavorMapper.queryByDishId(id));
        return Result.success(dishVo);
    }

    /**
     * 菜品修改
     * @param dishDTO
     * @return
     */
    @Transactional
    @Override
    public Result updateDish(DishDTO dishDTO) {
        //创建实体类并属性拷贝
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO,dish);
        //修改菜品
        dishMapper.update(dish);
        //判断是否有口味
        if(dishDTO.getFlavors() == null || dishDTO.getFlavors().isEmpty()) return Result.success();
        //删除菜品关联的口味
        dishFlavorMapper.deleteByDishId(Math.toIntExact(dish.getId()));
        //添加菜品关联的口味
        dishFlavorMapper.insertBatch(dishDTO.getFlavors(), dish.getId());
        return Result.success();
    }


    /**
     * 菜品状态修改
     * @param status
     * @param id
     * @return
     */
    @Override
    @Transactional
    public Result updateStatus(Integer status, String id) {
        //创建实体类并设置属性
        Dish dish = new Dish();
        dish.setStatus(status);
        dish.setId(Long.valueOf(id));
        //修改菜品状态
        dishMapper.update(dish);
        //返回成功
        return Result.success();
    }


    /**
     * 菜品分类查询
     * @param categoryId
     * @return
     */
    @Override
    public Result<List<Dish>> queryByCategoryId(Integer categoryId) {
        //根据分类id查询
        List<Dish> dishList = dishMapper.queryByCategory(categoryId);
        //判断是否启售
        List<Dish> result = new ArrayList<>();
        dishList.forEach(dish -> {
            if(dish.getStatus() == StatusConstant.ENABLE){
                result.add(dish);
            }
        });
        return Result.success(result);
    }

    /**
     * 菜品列表查询
     * @param categoryId
     * @return
     */
    @Override
    public Result<List<DishVO>> list(Long categoryId) {
        //查询缓存，有则直接返回
        Object o = redisTemplate.opsForValue().get(RedisConstant.SHOP_CATEGORY_DISH + categoryId);
        if(!ObjectUtils.isEmpty(o)){
            List<DishVO> dishVOS = JSONObject.parseArray(o.toString(), DishVO.class);
            return Result.success(dishVOS);
        }
        //查询菜品列表
        List<DishVO> dishVOS = dishMapper.queryByDishVoWithCategoryId(categoryId);
        //查询菜品口味信息，并判断是否启售
        dishVOS = dishVOS.stream().map(dishVO -> {
            if(dishVO.getStatus() == StatusConstant.ENABLE){
                dishVO.setFlavors(dishFlavorMapper.queryByDishId(Math.toIntExact(dishVO.getId())));
            }
            return dishVO;
        }).collect(Collectors.toList());
        //放入缓存
        redisTemplate.opsForValue().set(RedisConstant.SHOP_CATEGORY_DISH + categoryId, JSONObject.toJSONString(dishVOS), 2,TimeUnit.HOURS);
        return Result.success(dishVOS);
    }
}
